package com.augurit.common.system.web.org;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.springframework.beans.factory.annotation.Autowired;
import org.springside.modules.orm.Page;

import com.augurit.common.base.action.CrudActionSupport;
import com.augurit.common.base.action.ExtEditorGridSupport;
import com.augurit.common.base.extmodel.ExtEditorGridResult;
import com.augurit.common.base.extmodel.base.LinkCheckTreeNode;
import com.augurit.common.system.convert.AcApplicationConverter;
import com.augurit.common.system.service.org.IAcApplicationService;
import com.augurit.common.system.service.org.IAcRoleService;
import com.augurit.common.system.service.org.IAcServerService;
import com.augurit.common.system.util.OrgUtils;
import com.augurit.common.system.util.WebContextUtils;
import com.augurit.common.system.web.org.form.AcApplicationForm;
import com.augurit.common.system.web.org.form.AcRoleForm;
import com.augurit.common.util.ExtUtils;
import com.augurit.common.util.lang.CollectionUtils;
import com.augurit.common.util.lang.StringUtils;

@SuppressWarnings("serial")
@Results({
	@Result(name = CrudActionSupport.RELOAD, location = "ac-role.action", type = "redirect"),
	@Result(name = CrudActionSupport.SUCCESS, location = "/common/system/org/ac-role.jsp"),
	@Result(name = AcRoleAction.FUNC_TREE, location = "/common/system/org/ac-role-functree.jsp")
})
public class AcRoleAction extends ExtEditorGridSupport<AcRoleForm> {
	
	//JSP跳转
	private static final String FUNC_TREE = "funcTree";
	
	@Autowired
	private IAcServerService acServerService;
	
	@Autowired
	private IAcApplicationService acApplicationService;
	
	@Autowired
	private IAcRoleService roleService;
	
	@Autowired
	private IAcApplicationService appService;

	private Long roleId;   			//角色id
	private Long[] orgIds;			//与角色关联或不与角色关联的机构id数组
	private Long[] groupIds;		//与角色关联或不与角色关联的工作组id数组
	private Long[] userIds;			//与角色关联或不与角色关联的用户id数组
	private Long[] posIds;			//与角色关联或不与角色关联的岗位id数组
	private Long funcId;
	private Page<AcRoleForm> page = new Page<AcRoleForm>(15);

	private String newFuncIdsStr;
	private String oldFuncIdsStr;
	
	/**
	 * 系统默认调用入口
	 */
	@Override
	public String execute() throws Exception {
		return SUCCESS;
	}
	
	public String funcTree() throws Exception {
		Long[] funcIds = roleService.getFuncIdsByRoleId(roleId);
		this.setOldFuncIdsStr(StringUtils.convertLongArrayToString(funcIds, ","));
		return FUNC_TREE;
	}

	/**
	 * 分页获取角色对象列表
	 */
	@Override
	public String list() throws Exception {
		ExtUtils.initPageFromExtGridParam(this.getRequest(), page);
		roleService.getAllRoles(page, getFormForSearch());
		this.extRenderGridJson(page);
		return null;
	}
	
	/**
	 * 新增角色对象
	 */
	public String create() throws Exception {
		List<AcRoleForm> list = persistChangeForms();
		this.extRenderEditorGridResult(ExtEditorGridResult.getEditorGridCreateMessage(list), list, false);
		return null;
	}
	
	/**
	 * 更新角色对象
	 */
	public String update() throws Exception {
		List<AcRoleForm> list = persistChangeForms();
		this.extRenderEditorGridResult(ExtEditorGridResult.getEditorGridUpdateMessage(list), list, true);
		return null;
	}

	/**
	 * 删除角色对象
	 */
	public String delete() throws Exception {
		Long[] ids = result.getDeletedIds();
		roleService.deleteRoleCascade(ids);
		this.extRenderEditorGridResult(true, ExtEditorGridResult.getEditorGridDeleteMessage(ids));
		return null;
	}

	/**
	 * 保存新增或修改的角色对象
	 */
	private List<AcRoleForm> persistChangeForms() throws Exception{
		List<AcRoleForm> list = result.getChangedForms(AcRoleForm.class);	
		roleService.save(list);
		return list;
	}
	
	
	/**
	 * 一次性获得指定角色的功能权限check树
	 */
	public String getFuncRightCheckTree() throws Exception{
		
		//获取指定角色ID获取功能ID集合
		Long[] funcIds = roleService.getFuncIdsByRoleId(roleId);
		
		//获取应用列表缓存
		List<AcApplicationForm> appsBuffer = WebContextUtils.getAcApplicationList(
				acServerService, acApplicationService, false, this.getApplication());
		
		List<AcApplicationForm> appList = appService.getTreeByApps(appsBuffer, true);
		List<LinkCheckTreeNode> appNodeList = AcApplicationConverter.OneTimeConvertAllAppsToTree(appList, funcIds);
		
		this.extRenderListJson(appNodeList, false);

		return null;
	}
	
	/**
	 * 获取指定角色需要增加的功能ids
	 * @return
	 */
	private List<Long> getFuncIdsAddToRole(Long[] newFuncIds, Long[] oldFuncIds){
		List<Long> needAddFuncIds = null;
			needAddFuncIds = new ArrayList<Long>();
			if( newFuncIds != null && newFuncIds.length > 0){
				for(Long funcId:newFuncIds){
					if(Arrays.binarySearch(oldFuncIds, funcId) < 0){
						needAddFuncIds.add(funcId);
					}
				}
			}
		return needAddFuncIds;
	}
	
	/**
	 * 获取指定角色需要删除的功能ids
	 * @return
	 */
	private List<Long> getFuncIdsDeleteFromRole(Long[] newFuncIds,Long[] oldFuncIds){
		List<Long> needDeleteFuncIds = new ArrayList<Long>();
		if(oldFuncIds != null && oldFuncIds.length > 0){
			for(Long funcId:oldFuncIds){
				//如果原来的功能不在新的功能列表中
				if(Arrays.binarySearch(newFuncIds, funcId) < 0){
					needDeleteFuncIds.add(funcId);
				}
			}
		}
		return needDeleteFuncIds;
		
	}
	/**
	 * 修改角色关联的功能
	 * @return
	 * @throws Exception
	 */
	public String modifyFuncsOfRole() throws Exception{
		//获取角色原来具有的功能ids
		Long[] oldFuncIds = StringUtils.splitStringToArray(oldFuncIdsStr, ",");
		//获取用户最新选择的功能ids
		Long[] newFuncIds = StringUtils.splitStringToArray(newFuncIdsStr, ",");
		
		if(oldFuncIds == null){
			roleService.associateFuncToRole(roleId, newFuncIds);
		}
		else{
			Arrays.sort(oldFuncIds);
			
			if(newFuncIds == null ){
				roleService.disAssociateFuncFromRole(roleId, oldFuncIds);
			}
			else{
				Arrays.sort(newFuncIds);
				
				//修改角色的功能权限
				List<Long> needAddFuncIds = getFuncIdsAddToRole(newFuncIds,oldFuncIds);
				List<Long> needDeleteFuncIds = getFuncIdsDeleteFromRole(newFuncIds, oldFuncIds);
				if(needAddFuncIds != null && needAddFuncIds.size() > 0 )
					roleService.associateFuncToRole(roleId, CollectionUtils.toLongArray(needAddFuncIds));
				if(needDeleteFuncIds != null && needDeleteFuncIds.size() > 0)
					roleService.disAssociateFuncFromRole(roleId, CollectionUtils.toLongArray(needDeleteFuncIds));
			}
		}
		
		Long[] funcIds = roleService.getFuncIdsByUserId(this.getLoginUserId());
		this.getSession().setAttribute(WebContextUtils.SES_LOGIN_USER_FUNC, OrgUtils.convertToString(funcIds, ","));
		
		this.extRenderSuccess();
		return null;
	}
	
	/**
	 * 获取具有指定功能的用户
	 * @return
	 * @throws Exception
	 */
	public String getRolesByFuncId()throws Exception{
		ExtUtils.initPageFromExtGridParam(this.getRequest(), page);
		Long[] roleIds = roleService.getRoleIdsByFuncId(funcId);
		roleService.getRoles(page, roleIds);
		this.extRenderGridJson(page);
		return null;
	}
	
	/**
	 * 使机构与指定角色关联
	 * @return
	 * @throws Exception
	 */
	public String assignRoleToOrg() throws Exception{
		roleService.assignRoleToOrg(roleId, orgIds);
		this.extRenderSuccess();
		return null;
	}
	
	
	/**
	 * 使机构不与指定角色关联
	 * @return
	 * @throws Exception
	 */
	public String dissociateRoleFromOrg()throws Exception{
		roleService.disAssociateRoleFromOrg(roleId, orgIds);
		this.extRenderSuccess();
		return null;
	}
	
	/**
	 * 使工作组与指定角色关联
	 * @return
	 * @throws Exception
	 */
	public String assignRoleToGroup() throws Exception{
		roleService.assignRoleToGroup(roleId, groupIds);
		this.extRenderSuccess();
		return null;
	}
	
	/**
	 * 是工作组不与指定角色关联
	 * @return
	 * @throws Exception
	 */
	public String dissociateRoleFromGroup()throws Exception{
		roleService.disAssociateRoleFromGroup(roleId, groupIds);
		this.extRenderSuccess();
		return null;
	}
	
	/**
	 * 使用户与指定角色关联
	 * @return
	 * @throws Exception
	 */
	public String assignRoleToUser() throws Exception{
		roleService.assignRoleToUser(roleId, userIds);
		this.extRenderSuccess();
		return null;
	}
	
	
	/**
	 * 使用户不与指定角色关联
	 * @return
	 * @throws Exception
	 */
	public String dissociateRoleFromUser() throws Exception{
		roleService.disAssociateRoleFromUser(roleId, userIds);
		this.extRenderSuccess();
		return null;
	}
	
	
	/**
	 * 使岗位与指定角色关联
	 * @return
	 * @throws Exception
	 */
	public String assignRoleToPos() throws Exception{
		roleService.assignRoleToPosition(roleId, posIds);
		this.extRenderSuccess();
		return null;
	}
	
	/**
	 * 使岗位不与指定角色关联
	 * @return
	 * @throws Exception
	 */
	public String dissociateRoleFromPos()throws Exception{
		roleService.disAssociateRoleFromPos(roleId, posIds);
		this.extRenderSuccess();
		return null;
	}

	/**
	 * 获取查询条件值
	 */
	private AcRoleForm getFormForSearch(){
		AcRoleForm form = new AcRoleForm();
		form.setRoleCode(this.getRequest().getParameter("roleCode"));
		form.setRoleName(this.getRequest().getParameter("roleName"));
		return form;
	}
	
	//******************** 基本属性的getter和setter方法 ********************
	public Long getRoleId() {
		return roleId;
	}

	public void setRoleId(Long roleId) {
		this.roleId = roleId;
	}

	public Page<AcRoleForm> getPage() {
		return page;
	}

	public void setPage(Page<AcRoleForm> page) {
		this.page = page;
	}

	public Long[] getOrgIds() {
		return orgIds;
	}

	public void setOrgIds(Long[] orgIds) {
		this.orgIds = orgIds;
	}

	public Long[] getUserIds() {
		return userIds;
	}

	public void setUserIds(Long[] userIds) {
		this.userIds = userIds;
	}

	public Long[] getPosIds() {
		return posIds;
	}

	public void setPosIds(Long[] posIds) {
		this.posIds = posIds;
	}

	public Long getFuncId() {
		return funcId;
	}

	public void setFuncId(Long funcId) {
		this.funcId = funcId;
	}

	public String getNewFuncIdsStr() {
		return newFuncIdsStr;
	}

	public void setNewFuncIdsStr(String newFuncIdsStr) {
		this.newFuncIdsStr = newFuncIdsStr;
	}

	public String getOldFuncIdsStr() {
		return oldFuncIdsStr;
	}

	public void setOldFuncIdsStr(String oldFuncIdsStr) {
		this.oldFuncIdsStr = oldFuncIdsStr;
	}

	public Long[] getGroupIds() {
		return groupIds;
	}

	public void setGroupIds(Long[] groupIds) {
		this.groupIds = groupIds;
	}
}
